package com.example.service.impl;

import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.example.enums.ErrorCode;
import com.example.exception.BusinessException;
import com.example.model.dto.DrawDto;
import com.example.model.dto.ImageStyleTransDto;
import com.example.model.entity.Face;
import com.example.model.entity.RequestData;
import com.example.model.vo.ResponseVo;
import com.example.service.AiService;
import lombok.extern.slf4j.Slf4j;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author lzh
 */
@Service
@Slf4j
public class AiServiceImpl implements AiService {

    static final OkHttpClient HTTP_CLIENT = new OkHttpClient.Builder()
            // 设置连接超时为30秒
            .connectTimeout(80, TimeUnit.SECONDS)
            // 设置读取超时为60秒
            .readTimeout(80, TimeUnit.SECONDS)
            .build();

    @Value("${ai.path.address}")
    private String address;

    /**
     * lzh
     */
    private static final String TOKEN1 = "24.a65bd52b3bf0c66d541aca0ef50b921b.2592000.1720168192.282335-78141616";

    private static final String DRAW_TOKEN = "24.102b3b572be71a25ccd415a3b3622f82.2592000.1720615267.282335-80857382";
    /**
     * lwj
     */
    private static final String TOKEN2 = "24.b284cc9bb51677d9e9b1903fa54a4616.2592000.1720281802.282335-78888302";
    /**
     * lw
     */
    private static final String TOKEN3 = "24.342ee020fe9978bde0e95de48cd3ffb0.2592000.1720190042.282335-78926217";

    @Override
    public List<String> detectFace(String path) throws IOException {
        //取出请求路径文件名
        String[] paths = path.split("/");
        String fileName = paths[paths.length - 1];
        //真实图片存储路径
        String realPath = address + "/" + fileName;
        MediaType mediaType = MediaType.parse("application/json");
        RequestData requestData = new RequestData();
        requestData.setImage(getFileContentAsBase64(realPath));
        requestData.setImage_type("BASE64");
        requestData.setMax_face_num(20);
        requestData.setDisplay_corp_image(1);
        RequestBody requestBody = RequestBody.create(mediaType, JSONUtil.toJsonStr(requestData));
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/rest/2.0/face/v3/detect?access_token=24.a65bd52b3bf0c66d541aca0ef50b921b.2592000.1720168192.282335-78141616")
                .method("POST", requestBody)
                .addHeader("Content-Type", "application/json")
                .build();
        Response response = HTTP_CLIENT.newCall(request).execute();
        ResponseVo responseVo = null;
        if (response.body() != null) {
            responseVo = JSONUtil.toBean(response.body().string(), ResponseVo.class);
        }
        List<Face> faceList = null;
        if (responseVo != null) {
            faceList = responseVo.getResult().getFace_list();
        }
        List<String> imageList = new ArrayList<>();
        if (CollectionUtils.isEmpty(faceList)) {
            return imageList;
        }
        imageList = faceList.stream().map(Face::getCorp_image_base64).collect(Collectors.toList());
        return imageList;
    }

    @Override
    public String toAnime(String path) throws IOException {
        String localAddress = this.urlToLocalAddress(path);
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        RequestBody body = RequestBody.create(mediaType, "image=" + getFileContentAsBase64(localAddress, true));
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/rest/2.0/image-process/v1/selfie_anime?access_token=24.342ee020fe9978bde0e95de48cd3ffb0.2592000.1720190042.282335-78926217")
                .method("POST", body)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .addHeader("Accept", "application/json")
                .build();
        Response response = HTTP_CLIENT.newCall(request).execute();
        JSONObject responseJsonObject = JSONUtil.parseObj(response.body().string());
        String resultImageBase64 = responseJsonObject.getStr("image");
        if (resultImageBase64 == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR);
        }
        return resultImageBase64;
    }

    @Override
    public String AiDraw(DrawDto drawDto) throws IOException {
        String text = drawDto.getText();
        String style = drawDto.getStyle();
        String resolution = drawDto.getResolution();
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, "{\"text\":\"" + text + "\",\"resolution\":\"" + resolution + "\",\"style\":\"" + style + "\",\"num\":1}");
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/rpc/2.0/wenxin/v1/basic/textToImage?access_token=24.5a06eae79fc5161e6a9995be747fe1c0.2592000.1720406374.282335-78848806")
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
                .addHeader("Accept", "application/json")
                .build();
        Response response = HTTP_CLIENT.newCall(request).execute();
        JSONObject jsonObject = JSONUtil.parseObj(response.body().string());
        JSONObject dataObject = jsonObject.getJSONObject("data");
        String taskId = dataObject.getStr("taskId");
        System.out.println(taskId);
        return DrawResults(taskId);
    }

    /**
     * 根据第一次请求得到的任务id，等待并获取作图结果
     *
     * @param taskId 第一次请求得到的任务id
     * @return
     * @throws IOException
     */
    private String DrawResults(String taskId) throws IOException {
        MediaType mediaType = MediaType.parse("application/json");
        RequestBody body = RequestBody.create(mediaType, "{\"taskId\":\"" + taskId + "\"}");
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/rpc/2.0/wenxin/v1/basic/getImg?access_token=24.5a06eae79fc5161e6a9995be747fe1c0.2592000.1720406374.282335-78848806")
                .method("POST", body)
                .addHeader("Content-Type", "application/json")
                .addHeader("Accept", "application/json")
                .build();
        Response response = HTTP_CLIENT.newCall(request).execute();
        JSONObject jsonObject = JSONUtil.parseObj(response.body().string());
        JSONObject dataObject = jsonObject.getJSONObject("data");
        while (dataObject.getStr("img") == null) {
            String waitingStr = dataObject.getStr("waiting");
            try {
                Thread.sleep(Integer.parseInt(waitingStr) * 1000L);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            response = HTTP_CLIENT.newCall(request).execute();
            jsonObject = JSONUtil.parseObj(response.body().string());
            dataObject = jsonObject.getJSONObject("data");
        }
        String image = dataObject.getStr("img");
        System.out.println(image);
        return image;
    }

    @Override
    public String imageStyleTrans(ImageStyleTransDto imageStyleTransDto) throws IOException {
        String path = imageStyleTransDto.getPath();
        String localAddress = this.urlToLocalAddress(path);
        MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
        RequestBody body = RequestBody.create(mediaType, "option=" + imageStyleTransDto.getOption() + "&image=" + getFileContentAsBase64(localAddress, true));
        Request request = new Request.Builder()
                .url("https://aip.baidubce.com/rest/2.0/image-process/v1/style_trans?access_token=24.342ee020fe9978bde0e95de48cd3ffb0.2592000.1720190042.282335-78926217")
                .method("POST", body)
                .addHeader("Content-Type", "application/x-www-form-urlencoded")
                .addHeader("Accept", "application/json")
                .build();
        Response response = HTTP_CLIENT.newCall(request).execute();
        JSONObject responseJsonObject = JSONUtil.parseObj(response.body().string());
        String resultImageBase64 = responseJsonObject.getStr("image");
        if (resultImageBase64 == null) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR);
        }
        return resultImageBase64;
    }

    /**
     * 将图片url转成本地路径
     */
    public String urlToLocalAddress(String url) {
        int startIndex = url.indexOf("avatar/") + "avatar/".length();
        String fileName = null;
        if (startIndex > 0) {
            fileName = url.substring(startIndex);
        }
        return address + '/' + fileName;
    }

    /**
     * 获取文件base64编码
     *
     * @param path 文件路径
     * @return base64编码信息，不带文件头
     * @throws IOException IO异常
     */
    private static String getFileContentAsBase64(String path) throws IOException {
        byte[] b = Files.readAllBytes(Paths.get(path));
        return Base64.getEncoder().encodeToString(b);
    }

    /**
     * 获取文件base64编码
     *
     * @param path      文件路径
     * @param urlEncode 如果Content-Type是application/x-www-form-urlencoded时,传true
     * @return base64编码信息，不带文件头
     * @throws IOException IO异常
     */
    private static String getFileContentAsBase64(String path, boolean urlEncode) throws IOException {
        byte[] b = Files.readAllBytes(Paths.get(path));
        String base64 = Base64.getEncoder().encodeToString(b);
        if (urlEncode) {
            base64 = URLEncoder.encode(base64, "utf-8");
        }
        return base64;
    }

}
